﻿P.Module.define("GridItems", [],
    function()
    {
        var e = "activeItem",
            t = 3,
            n = 1e3,
            i = 3e3,
            o = 1e3,
            s = "gridSortable",
            r = {
                UP: 0,
                DOWN: 1
            },
            a = function(e)
            {
                var t = parseInt(e.replace("px", ""), 10);
                return isNaN(t) ? 0 : t;
            },
            l = function(e)
            {
                this.childModule = e,
                this.top = null,
                this.height = null,
                this.bottom = null,
                this.$itemWrapper = e.getParentElement().closest(".item"),
                this.columnIndex = null,
                this.inDom = !0;
            };
        l.prototype = {
            _calculateHeight: function()
            {
                this.height = this.$itemWrapper.height();
            },
            ensureHeightCalculated: function()
            {
                null === this.height && this._calculateHeight();
            },
            recalculateHeight: function()
            {
                this.inDom ? this._calculateHeight() : this.log.error("Cannot calculate height because this item is not inDom");
            },
            setPosition: function(e, t)
            {
                this.top = e,
                this.bottom = t;
            },
            hasPosition: function()
            {
                return null !== this.top;
            }
        };
        var u = function(e, t)
        {
            this.gridItems = e,
            this.options = t,
            this.shortestColumnIndex = 0,
            this.columnLengths = [],
            this.childCidToItemInfo = {};
            var n = this;
            _.each(this.gridItems.children,
                function(e)
                {
                    n.childCidToItemInfo[e.cid] = new l(e);
                });
        };
        u.prototype = {
            getFilledHeight: function()
            {
                return this.columnLengths[this.shortestColumnIndex];
            },
            onChildRendered: function(e)
            {
                this._reflowOnChildChanged(e);
            },
            onChildAdded: function(e)
            {
                this.childCidToItemInfo[e.cid] = new l(e);
            },
            onChildRemoved: function(e, t)
            {
                if (!this.gridItems.isEmptying)
                {
                    t.remove();
                    var n = this.childCidToItemInfo[e.cid],
                        i = n.columnIndex;
                    delete this.childCidToItemInfo[e.cid],
                    this._reflowColumnContent(i);
                }
            },
            empty: function()
            {
                this.childCidToItemInfo = {};
            },
            onChildContentChanged: function(e)
            {
                this._reflowOnChildChanged(e);
            },
            onChildDimsChanged: function(e)
            {
                this._reflowOnChildChanged(e, !1);
            },
            _reflowOnChildChanged: function(e, t)
            {
                var n = this.childCidToItemInfo[e.cid];
                n.recalculateHeight(),
                this._reflowColumnContent(n.columnIndex, t);
            },
            _reflowColumnContent: function(e, t)
            {
                void 0 === t && (t = this.options.reflow_all),
                t ? this.positionGrid() : this._repositionItemsInColumn(e);
            },
            //列显示 排列
            _calculateNumColumns: function()
            {
                var e = this.options.minimum_num_columns || t;
                if (!this.itemWidth)
                {
                    return e;
                }
                this.options.centered || this.gridItems.$el.css("width", "auto");
                var n = this.gridItems.getWidth(!1),
                    i = Math.floor(n / this.itemWidth);
                return Math.max(e, i);
            },
            //获取位置
            _positionItemInColumn: function (e, t)
            {
                //t 当前列号
                if (this.gridItems.isReady())
                {
                    //n是一个保护 项目的 对象
                    // i <div class=\"Pin Module summary\"> 一节
                    var n = this.childCidToItemInfo[e.cid],
                        i = n.$itemWrapper;
                    t = Math.max(0, t),
                    t = Math.min(this.columnLengths.length - 1, t);
                    //多少列就多少个值
                    //this.columnLengths	[0,0,0,0,0]
                    //以当前列为index 
                    var o = this.columnLengths[t];
                    i.css({
                        top: o + "px",
                        left: t * this.itemWidth + "px",
                        visibility: "visible"
                    }),
                    n.columnIndex = t;
                    //height div 的高度
                    //topBuffer 上方间隔
                    //bottomBuffer 下方间隔
                    var s = n.height + this.topBuffer + this.bottomBuffer,
                        r = o + s;//当前列,下一个项的top值
                    n.setPosition(o, r),
                    //保存 bottom值
                    this.columnLengths[t] = r,
                    this._setShortestColumnIndex();
                }
            },
            _positionItem: function(e)
            {
                if (this.gridItems.isReady())
                {
                    if (0 === this.columnLengths.length)
                    {
                        if (!this.itemWidth)
                        {
                            var t = this.childCidToItemInfo[e.cid],
                                n = t.$itemWrapper;
                            this.itemWidth = n.outerWidth(!0);
                            var i = n.css("margin-top"),
                                o = n.css("padding-top"),
                                s = n.css("margin-bottom"),
                                r = n.css("padding-bottom");
                            this.topBuffer = a(i) + a(o),
                            this.bottomBuffer = a(s) + a(r);
                        }
                        var l = this._calculateNumColumns();
                        this.options.centered || this.gridItems.$el.css("width", l * this.itemWidth),
                        this.columnLengths = Array(l),
                        this._setShortestColumnIndex();
                    }
                    var u = this.shortestColumnIndex;
                    this._positionItemInColumn(e, u);
                }
            },
            _setShortestColumnIndex: function()
            {
                this.shortestColumnIndex = 0;
                for (var e = 0; e < this.columnLengths.length; e++)
                {
                    this.columnLengths[e] = this.columnLengths[e] || 0,
                    this.columnLengths[e] < this.columnLengths[this.shortestColumnIndex] && (this.shortestColumnIndex = e);
                }
            },
            _repositionItemsInColumn: function(e)
            {
                if (this.gridItems.isReady())
                {
                    var t = this;
                    this.columnLengths[e] = 0;
                    var n = _.filter(this.childCidToItemInfo,
                        function(t)
                        {
                            return t.columnIndex === e;
                        }),
                        i = _.sortBy(n,
                            function(e)
                            {
                                return e.top;
                            });
                    _.each(i,
                        function(n)
                        {
                            t._positionItemInColumn(n.childModule, e);
                        }),
                    this.resizeContainer();
                }
            },
            resizeGrid: function()
            {
                var e = this.columnLengths.length,
                    t = this._calculateNumColumns();
                e !== t && (this.positionGridChildren(), this.gridItems.rearrangeItems(!0));
            },
            resizeContainer: function()
            {
                var e = Math.max.apply(Math, this.columnLengths);
                this.gridItems.$el.css("height", e + "px"),
                this.gridItems.triggerEvent(P.CONST.EVENT_CONTENT_CHANGED, null, !0);
            },
            positionGrid: function()
            {
                this.gridItems.isReady() && (this.positionGridChildren(), this.gridItems.rearrangeItems());
            },
            //设置项的位置
            positionGridChildren: function(e)
            {
                if (this.gridItems.isReady())
                {
                    var t = this;
                    e || (this.columnLengths = []),
                    _.each(this.gridItems.children,
                        function(e)
                        {
                            var n = t.childCidToItemInfo[e.cid];
                            n.ensureHeightCalculated();
                        }),
                    _.each(this.gridItems.children,
                        function(n)
                        {
                            var i = t.childCidToItemInfo[n.cid];
                            e && i.hasPosition() || t._positionItem(i.childModule);
                        }),
                    this.resizeContainer();
                }
            },
            hideAndShowItems: function(e, t, n, i, o)
            {
                var s = this,
                    a = [],
                    l = [];
                _.each(this.childCidToItemInfo,
                    function(s)
                    {
                        var u = s.$itemWrapper[0];
                        s.bottom < i ? e && s.inDom && (t || n !== r.DOWN || (a.push(u), s.inDom = !1)) : s.top > o ? e && s.inDom && (t || n !== r.UP || (a.push(u), s.inDom = !1)) : s.inDom || (l.push(u), s.inDom = !0);
                    }),
                (l.length > 0 || a.length > 0) && P.deferDomManipulation(function()
                {
                    s.gridItems.log.debug("hideAndShowItems DOM manip showing ", l.length, " hiding ", a.length);
                    var e;
                    if (l.length > 0)
                    {
                        var t = document.createDocumentFragment();
                        for (e = 0; e < l.length; e++)
                        {
                            t.appendChild(l[e]);
                        }
                        s.gridItems.$el[0].appendChild(t);
                    }
                    for (e = 0; e < a.length; e++)
                    {
                        var n = a[e];
                        n.parentNode && n.parentNode.removeChild(n);
                    }
                });
            }
        };
        var c = function(e, t)
        {
            this.gridItems = e,
            this.options = t;
        };
        c.prototype = {
            resizeGrid: function()
            {
            },
            onChildContentChanged: function()
            {
            },
            onChildDimsChanged: function()
            {
            },
            onChildRendered: function()
            {
            },
            onChildAdded: function()
            {
            },
            positionGridChildren: function()
            {
            },
            empty: function()
            {
            },
            positionGrid: function()
            {
                this.gridItems.isReady() && this.gridItems._requestMoreItemsIfNeeded();
            },
            hideAndShowItems: function()
            {
            },
            onChildRemoved: function(e, t)
            {
                t.remove(),
                this.gridItems.triggerEvent(P.CONST.EVENT_CONTENT_CHANGED, null, !0);
            },
            getFilledHeight: function()
            {
                var e = this.gridItems.getWidth(!1),
                    t = this.gridItems.children.length;
                if (0 === t)
                {
                    return 0;
                }
                var n = this.gridItems.children[0],
                    i = n.$el.outerWidth(!0),
                    o = n.$el.outerHeight(!0),
                    s = Math.floor(e / i),
                    r = Math.ceil(t / s),
                    a = 0 !== t % s,
                    l = r * o;
                return a && (l -= o),
                l;
            }
        };
        var d = function(e, t, n, i)
        {
            this.gridItems = e,
            t || (t = {}),
            t = _.extend({
                    containment: "parent",
                    cursor: "move",
                    items: "." + s,
                    zIndex: o
                },
                t),
            this.gridItems.$el.sortable(t),
            this.childModuleName = n,
            this.idFn = i,
            this._setSortableMetadata();
        };
        d.prototype = {
            _setSortableMetadata: function()
            {
                var e = this;
                _.each(this.gridItems.getChildrenByModuleName(this.childModuleName),
                    function(t)
                    {
                        e._setSortableMetadataOnModule(t);
                    });
            },
            _setSortableMetadataOnModule: function(e)
            {
                e.$el.attr("data-sort-id", this.idFn(e));
                var t = e.getParentElement();
                t.addClass(s);
            },
            onChildAdded: function(e)
            {
                this._setSortableMetadataOnModule(e);
            },
            getSortOrder: function()
            {
                var e = [];
                return _.each(this.gridItems.$el.find("." + this.childModuleName),
                    function(t)
                    {
                        e.push($(t).attr("data-sort-id"));
                    }),
                e;
            }
        };
        var h = P.Module.extend({
            events: {
                "click .trackActiveItem .item": "onTrackItemClick"
            },
            mixins: [P.Mixins.PreventScroll],
            onChildNavigate: function(e)
            {
                var t = e.currentTarget;
                this.updateActiveItem(t.getParentElement());
            },
            onTrackItemClick: function(e)
            {
                var t = e.currentTarget;
                this.updateActiveItem($(t));
            },
            updateActiveItem: function(t)
            {
                var n = this.$(".activeItem");
                n.removeClass(e),
                t.addClass(e);
            },
            initialize: function()
            {
                this._scrollListener = null,
                this.alreadyInitialized = !1,
                this.scrollTop = 0,
                this.lastScrollTop = null,
                this.viewableHeight = null,
                this.lastTopBorder = null,
                this.lastBottomBorder = null,
                this.layoutManager = null,
                this.childListen(P.CONST.EVENT_CONTENT_CHANGED, this.onChildContentChanged),
                this.childListen(P.CONST.EVENT_DIMS_CHANGED, this.onChildDimsChanged);
            },
            initializeSortManager: function(e, t, n)
            {
                this.sortManager = new d(this, e, t, n);
            },
            getSortOrder: function(e, t)
            {
                return this.sortManager ? this.sortManager.getSortOrder(e, t) : void 0;
            },
            onOptionsChanged: function()
            {
                this._setScrollableElement(),
                this.alreadyInitialized = !1;
            },
            onResourceChanged: function()
            {
                this.alreadyInitialized = !1;
            },
            prependChildItem: function(e)
            {
                var t = 0;
                this.children.length > 0 && this.children[0].options.anchored && (t = 1),
                this.insertChild(e, this.$el, t),
                this.layoutManager.positionGrid();
            },
            prependNewItems: function(e, t)
            {
                var n = this,
                    i = 0,
                    o = this.resource.copy();
                o.resetBookmark(),
                o.set("prepend", !0),
                o.set("page_size", e);
                var s = new h({
                    resource: o
                });
                this.children.length > 0 && this.children[0].options.anchored && (i = 1),
                s.options = this.options,
                s.render(function()
                {
                    _.each(s.children.reverse(),
                        function(e)
                        {
                            e.remove(),
                            n.insertChild(e, n.$el, i);
                        }),
                    n.layoutManager.positionGrid(),
                    t && t();
                });
            },
            requestMoreItems: function()
            {
                this.isReady() && this._requestMoreItems();
            },
            hasMoreItems: function()
            {
                return !this.resource.atEnd();
            },
            _triggerIfItemsEnd: function()
            {
                this.hasMoreItems() || this.triggerEvent(P.CONST.EVENT_ITEMS_END, null, !0);
            },
            setPageSize: function(e)
            {
                this.resource.set("page_size", e);
            },
            onAddedToDom: function()
            {
                this.resizeListener = this.listen(P.Viewport, P.CONST.EVENT_RESIZE, this.onResize),
                this.navigateListener = this.childListen(P.CONST.EVENT_NAVIGATE, this.onChildNavigate),
                this._setUpGrid(),
                this.onResize();
            },
            onResize: function()
            {
                this.isReady() && this.layoutManager.resizeGrid();
            },
            hasItems: function()
            {
                return this.children.length > 0;
            },
            onContentReady: function()
            {
                var e = this.options.layout;
                if (e && "variable_height" !== e)
                {
                    if ("fixed_height" !== e)
                    {
                        return this.log.error('GridItems invalid value for "layout"', e),
                        void 0;
                    }
                    this.layoutManager = new c(this, this.options);
                }
                else
                {
                    this.layoutManager = new u(this, this.options);
                }
                this._setUpGrid(),
                this._triggerIfItemsEnd();
            },
            onRemovedFromDom: function()
            {
                this._scrollListener && (this.removeListener(this._scrollListener), this._scrollListener = null),
                this.stopPreventScroll(),
                this.navigateListener && this.removeListener(this.navigateListener),
                this.resizeListener && this.removeListener(this.resizeListener);
            },
            scrollToActiveItem: function(e)
            {
                var t = e.height(),
                    n = this.$(".activeItem"),
                    i = n.offset().top;
                e.scrollTop(i - t);
            },
            onChildContentChanged: function(e)
            {
                e.stopPropagation();
                var t = e.currentTarget;
                this.isReady() && (this.layoutManager.onChildContentChanged(t), this.rearrangeItems(!0));
            },
            onChildDimsChanged: function(e)
            {
                e.stopPropagation();
                var t = e.currentTarget;
                this.isReady() && this.layoutManager.onChildDimsChanged(t);
            },
            onChildRendered: function(e)
            {
                this.isReady() && this.layoutManager.onChildRendered(e);
            },
            onChildAdded: function(e)
            {
                var t = e.getParentElement();
                if (!t.hasClass("item"))
                {
                    var n = $("<div></div>").addClass("item");
                    n.insertBefore(e.getElement()),
                    n.append(e.getElement()),
                    t = n;
                }
                this.layoutManager && this.layoutManager.onChildAdded(e),
                this.sortManager && this.sortManager.onChildAdded(e);
            },
            onChildRemoved: function(e, t)
            {
                this.layoutManager && this.layoutManager.onChildRemoved(e, t);
            },
            empty: function()
            {
                this.isEmptying = !0,
                P.Module.prototype.empty.call(this),
                this.alreadyInitialized = !1,
                this.contentReady = !1,
                this.layoutManager && this.layoutManager.empty(),
                this.isEmptying = !1;
            },
            handleError: function(e)
            {
                this.pendingMoreRequest ? this.$(".errorMessage").remove() : P.Module.prototype.handleError.call(this, e);
            },
            _setUpGrid: function()
            {
                this._setScrollableElement(),
                this.isReady() && !this.alreadyInitialized && (this.layoutManager.positionGrid(), this.alreadyInitialized = !0);
            },
            _setScrollableElement: function()
            {
                this._scrollListener && (this.removeListener(this._scrollListener), this._scrollListener = null),
                this.scrollableElement = this.getScrollableElement(),
                this.options.scrollable && (this._scrollListener = this.listen(this.scrollableElement, "scroll", this._onScroll)),
                this._preventDefaultIfNeeded();
            },
            isReady: function()
            {
                return this.inDom && this.contentReady;
            },
            rearrangeItems: function()
            {
                this._requestMoreItemsIfNeeded(),
                this._hideAndShowItems();
            },
            _onScroll: function()
            {
                this.lastScrollTop = this.scrollTop,
                this.scrollTop = this.getScrollableElement().scrollTop(),
                this.rearrangeItems(!1);
            },
            _hideAndShowItems: function(e)
            {
                if (this.options.virtualize)
                {
                    e = e || !1;
                    var t = !this.lastScrollTop || this.scrollTop >= this.lastScrollTop ? r.DOWN : r.UP,
                        n = this.scrollTop - this.offsetFromScrollElement,
                        o = n + this.viewableHeight,
                        s = n - i,
                        a = o + i,
                        l = null === this.lastTopBorder || null === this.lastBottomBorder || n < this.lastTopBorder || o > this.lastBottomBorder;
                    (l || e) && (this.layoutManager.hideAndShowItems(e, this.pendingMoreRequest, t, s, a), this.lastTopBorder = s, this.lastBottomBorder = a),
                    e || this.scheduleHideShowItems();
                }
            },
            scheduleHideShowItems: _.debounce(function()
            {
                this._hideAndShowItems(!0);
            },
                n),
            onRendered: function()
            {
                this._requestMoreItemsIfNeeded();
            },
            _requestMoreItemsIfNeeded: function()
            {
                if (this.isReady() && this.options.scrollable && !this.pendingMoreRequest && !this.hasError && this.hasMoreItems())
                {
                    this.viewableHeight = this.scrollableElement.height(),
                    this.offsetFromScrollElement = this.$el.positionAncestor(this.scrollableElement).top;
                    var e = this.offsetFromScrollElement + this.layoutManager.getFilledHeight();
                    e - (this.viewableHeight + this.scrollTop) > 2 * this.viewableHeight || this._requestMoreItems();
                }
            },
            _requestMoreItems: function(e)
            {
                _.isUndefined(e) && (e = 2),
                this.triggerEvent(P.CONST.EVENT_ITEMS_REQUEST_START, null, !0),
                this.pendingMoreRequest = !0;
                var t = this,
                    n = this.renderAppend(function()
                    {
                        t.layoutManager.positionGridChildren(!0),
                        t.pendingMoreRequest = !1,
                        t.hasError && (t.triggerEvent(P.CONST.EVENT_ERROR_RESOLVED, null, !0), t.hasError = !1),
                        t.triggerEvent(P.CONST.EVENT_ITEMS_REQUEST_SUCCESS, null, !0),
                        t._requestMoreItemsIfNeeded(),
                        t._triggerIfItemsEnd();
                    },
                        function()
                        {
                            e > 0 ? t._requestMoreItems(e - 1) : (t.pendingMoreRequest = !1, t.hasError = !0, t.triggerEvent(P.CONST.EVENT_ERROR, null, !0), t._triggerIfItemsEnd()),
                            this.log.error("in grid append");
                        });
                return n || (t.pendingMoreRequest = !1),
                n;
            },
            _preventDefaultIfNeeded: function()
            {
                this.options.prevent_default_scroll && this.startPreventScroll(this.scrollableElement, this.$el);
            }
        });
        return h;
    });